/**
 * Class: LNEditor
 *		Редактор в стиле medium
 */
function LNEditor(options)
{
	this.options=options;
	this.element=options.element;
	this.upload_data = options.upload_data;
	this.save_func = options.save_func;
	this.on_image_upload_func = options.on_image_upload_func;
	this.init();

	// Список кнопок
	this.options={
		i:{command:"italic",arg:"",value:"I"},
		b:{command:"bold",arg:"",value:"B"},
		u:{command:"underline",arg:"",value:"U"},
		quote:{command:"formatBlock",arg:"blockquote",value:"“”",toggle:true}
	};
	
	// Список возможных стилей (шаблонов блоков)
	
	// Список возможных стилей (шаблонов блоков)
	
	
	this.styles={
		"1": {
			template:
				"<div data-id='1' class='block1 block'>"+
					"<div class='left'><h1 class='editable-text text field' contenteditable='true' data-tags='' data-name='header' data-empty-func='text' data-placeholder='Введите заголовок'></h1><div class='editable-image field' data-preview='5' data-name='image' data-empty='/images/empty-image-block1.png' class='img'></div></div>"+
					"<div class='right'><div class='editable-text text field' contenteditable='true' data-options='i,b,u,quote' data-tags='stdfmt' data-name='body' data-empty-func='p' data-placeholder='<p>Введите текст...</p>'></div></div>"+
					"<div class='cl'></div>"+
					"<div class='remove_block' onclick='$(this).parent().remove()'>удалить блок</div>"+
				"</div>",
			fields:[
				'header',
				'image',
				'body',
			]
			
		},
		"2": {
			template:
				"<div data-id='2' class='block2 block'>"+
					"<div class='editable-text text field' contenteditable='true' data-options='i,b,u,quote' data-tags='stdfmt' data-name='body' data-empty-func='p' data-placeholder='<p>Введите текст...</p>'></div>"+
					"<div class='cl'></div>"+
					"<div class='remove_block' onclick='$(this).parent().remove()'>удалить блок</div>"+
				"</div>",
			fields:[
				'body',
			]
		},
		"3": {
			template:
				"<div data-id='3' class='block3 block'>"+
					"<div class='left'><div class='editable-text text field' contenteditable='true' data-options='i,b,u,quote' data-tags='stdfmt' data-name='body1' data-empty-func='p' data-placeholder='<p>Введите текст...</p>'></div></div>"+
					"<div class='right'>"+
						"<h1 class='editable-text text field' contenteditable='true' data-tags='' data-name='header' data-empty-func='text' data-placeholder='Введите заголовок'></h1>"+
						"<div class='editable-image text field' data-name='image'  data-preview='5' class='img' data-empty='/images/empty-image-block3.png'></div>"+
						"<div class='cols'>"+
							"<div class='col'><div class='editable-text text field' contenteditable='true' data-options='i,b,u,quote' data-tags='stdfmt' data-name='body2' data-empty-func='p' data-placeholder='<p>Введите текст...</p>'></div></div>"+
							"<div class='col'><div class='editable-text text field' contenteditable='true' data-options='i,b,u,quote' data-tags='stdfmt' data-name='body3' data-empty-func='p' data-placeholder='<p>Введите текст...</p>'></div></div>"+
							"<div class='cl'></div>"+
						"</div>"+
					"</div>"+
					"<div class='cl'></div>"+
					"<div class='remove_block' onclick='$(this).parent().remove()'>удалить блок</div>"+
				"</div>",
			fields:[
				'header',
				'image',
				'body1',
				'body2',
				'body3',
			]
		}
	};
}
/**
 * Method: init
 *		Инициализирует
 */
LNEditor.prototype.init=function()
{
	var t = this;
	this.element.addClass(t.options.cssclass || 'LNEditor');
	this.editarea=$('<div class="editarea"></div>').appendTo(this.element);
	this.action_block=$('<div class="action_block"></div>').appendTo(this.element);
	
	this.action_block.html('<div class="item" data-id="1">1</div><div class="item" data-id="2">2</div><div class="item" data-id="3">3</div><div class="item" data-id="save">save</div><div class="cl"></div>');
	$(".item",this.action_block).each(function(i,tag) {
		tag=$(tag);		
		tag.bind("mouseup"	,function(e) {			
			if (tag.attr('data-id')=='save') {
				t.save();
				return;
			}
			t.add_block({
				style_id:tag.attr('data-id'),
				content:{}
			});
		});
	});
}
/**
 * Method: add_block
 *		Добавляет редактируемый блок с нужным дизайном
 *
 * Parameters:
 *		data typeof Object				- Конфиг
 *		data.style_id typeof Integer	- ID стиля
 *		data.content typeof Object		- Уже существующие данные для блока
 */
LNEditor.prototype.add_block=function(data)
{

	var t=this;
	var style=this.styles[data.style_id];
	var tmpl=style.template;
	tmpl=$(tmpl);
	$(".editable-text",tmpl).each(function(i,tag) {
		tag=$(tag);
		var content=data.content[tag.attr("data-name")];
		if (content==undefined) {
			content=tag.attr("data-placeholder");
			tag.addClass("editable-placeholder");
		}
		tag.html(content);
		tag.bind("focus"	,function(e) { console.log('focus'); t.editable_text_focus(tag); });
		tag.bind("blur"		,function(e) { console.log('blur'); t.editable_text_blur(tag); });
		tag.bind("selectend",function(e) { console.log('selectend'); t.editable_text_select(tag,e); });
		tag.bind("keyup"	,function(e) { console.log('keyup'); t.editable_text_keyup(tag); });
		tag.bind("mouseup"	,function(e) { console.log('mouseup'); t.editable_text_mouseup(tag); });
		tag.bind("paste"	,function(e) { console.log('paste'); t.editable_text_paste(tag,e); });
	});
	$(".editable-image",tmpl).each(function(i,tag) {
		tag = $(tag);
		
		var image = {
			//url: data.content[tag.attr("data-name")]||tag.attr("data-empty"),
			//preview: data.content[tag.attr("data-name")] ? tag.attr("data-preview"):'' || '',
			url: tag.attr("data-empty"),
			preview: '',
			id: tag.attr("data-id"),
			resize_data : data.content[tag.attr("data-name")]
		};
		
		//resize_data.resize_data = data.content[tag.attr("data-name")];
		
		//var rd;
		//if(data.resize_data) rd = data.resize_data[tag.attr("data-name")];
		
		//image.resize_data = rd;
		
		t.load_image(image,tag);
		t.init_image_uploader(tag);
	});
	$(this.editarea).append(tmpl);
	
	
	
}
/**
 * Method: load_image
 *		Меняет картинку
 */
LNEditor.prototype.load_image=function(image,tag)
{
	var t =this;
	var preview = image.preview;
	var image_url = image.url;
	//if(preview)image_url = image_url.replace('.','-preview'+preview+'.');
	var img=new Image();
	
	img.src=image_url;
	tag.css("background-image","url("+image_url+")");
	tag.attr('data-url',image_url);
	tag.attr('data-id',image.id);
	
	img.onload=function() {
		tag.height(img.height);
		if (t.on_image_upload_func) t.on_image_upload_func(image,tag);
	};

	
}

/**
 * Method: editable_text_focus
 *		Срабатывает при получении фокуса на редактируемый блок текста
 *		Нужен для удаления placeholder текста и класса
 *
 * Parameters:
 *		tag typeof jQuery		- Редактируемый блок на который был фокус
 */
LNEditor.prototype.editable_text_focus=function(tag)
{
	var empty_func = 'empty_func__'+tag.attr("data-empty-func");	
	this[empty_func](tag,true);
	
	//if (tag.hasClass("editable-placeholder")) {
	//	tag.removeClass("editable-placeholder");
	//	console.log(tag.attr("data-empty"));
		
	//this.empty_func__text
	
		//if (tag.attr("data-empty")=='') {
		//	tag.html(tag.attr("data-empty"));	
		//} else {
			//tag.html(tag.attr("data-empty"));	
		//	$('p',tag).html('&nbsp;');
		//}
		
		//if (tag.attr("data-empty")!="") {
		//	$("*",tag).eq(0).focus()
			//console.log();
			//console.log(tag.focus());
		//}
	//}
//	this.edit_options_show(tag);
}

LNEditor.prototype.empty_func__text=function(tag,is_focus)
{
	if (is_focus) {
		if (tag.hasClass("editable-placeholder")) {
			tag.removeClass("editable-placeholder");
			tag.html("");
		}		
	} else {
		if (tag.html()=="") {
			tag.addClass("editable-placeholder");
			tag.html(tag.attr("data-placeholder"));
		}
	}
}

LNEditor.prototype.empty_func__p=function(tag,is_focus)
{
	
	if (is_focus) {
		if (tag.hasClass("editable-placeholder")) {
			tag.removeClass("editable-placeholder");
			$("p",tag).html("&nbsp;");
		}		
	} else {
		var html=tag.html();
		if (html=="" || html=="<p></p>" || html=="<p>&amp;nbsp;</p>" || html=="<p>&nbsp;</p>") {
			tag.addClass("editable-placeholder");
			tag.html(tag.attr("data-placeholder"));
		}
	}
}


/**
 * Method: editable_text_blur
 *		Срабатывает при ухода фокуса с редактируемого блока текста
 *		Нужен для возвращения placeholder текста и класса если блок не заполнен
 *
 * Parameters:
 *		tag typeof jQuery		- Редактируемый блок на который был blur
 */
LNEditor.prototype.editable_text_blur=function(tag)
{
	var t=this;
	var empty_func = 'empty_func__'+tag.attr("data-empty-func");	
	this[empty_func](tag,false);
	
	//console.log('editable_text_blur',tag.html());
	
	//if (tag.html()==tag.attr("data-empty")) {
	//if (tag.html()=="") {
		
	//	tag.addClass("editable-placeholder");
	//	tag.html(tag.attr("data-placeholder"));
	//}
	//setTimeout(function() {t.edit_options_hide();},10);
}

/**
 * Method: editable_text_select
 *		Срабатывает при выборе текста
 *
 * Parameters:
 *		tag typeof jQuery		- Редактируемый блок на который был select
 *		e typeof jQueryEvent	- Событие
 */
LNEditor.prototype.editable_text_select=function(tag,e)
{
	var selection=document.getSelection();
	if (selection.toString()=="") {
		this.edit_options_hide(tag);
		return;
	}
//	console.log(a);
	var range = selection.getRangeAt(0);
	var boundary = range.getBoundingClientRect();
	this.edit_options_show(tag,{x:(boundary.left + boundary.right) / 2,y:boundary.top});
	
}

/**
 * Method: editable_text_keyup
 *		Срабатывает при нажатии на клавишу
 *
 * Parameters:
 *		tag typeof jQuery		- Редактируемый блок на котором было событие
 *		e typeof jQueryEvent	- Событие
 */
LNEditor.prototype.editable_text_keyup=function(tag,e)
{
	this.editable_text_cleanup_start(tag);
	this.editable_text_select(tag,e);
}

/**
 * Method: editable_text_mouseup
 *		Срабатывает при отпускании мышки
 *
 * Parameters:
 *		tag typeof jQuery		- Редактируемый блок на котором было событие
 *		e typeof jQueryEvent	- Событие
 */
LNEditor.prototype.editable_text_mouseup=function(tag,e)
{
	this.editable_text_select(tag,e);
}

/**
 * Method: editable_text_cleanup_start
 *		Инициализурует с задержкой очистку блока от "неверных" тегов
 *
 * Parameters:
 *		tag typeof jQuery		- Редактируемый блок который надо очистить
 */
LNEditor.prototype.editable_text_cleanup_start=function(tag)
{
	var t=this;
	if (this._editable_text_cleanup_timeout) clearTimeout(this.editable_text__cleanup_timeout);
	this._editable_text_cleanup_timeout=setTimeout(function() { t._editable_text_cleanup_timeout=undefined;t.editable_text_cleanup(tag);},300);
}

/**
 * Method: _clean_attrs
 *		Вычищает аттрибуты из тега
 *
 * Parameters:
 *		tag typeof HTMLElement		- Тег для очистки
 */
LNEditor.prototype._clean_attrs=function(tag)
{
	if (tag.attributes.length==0) return;
	console.log("tag before removing attributes",tag);
	for (var i=0;i<tag.attributes.length;i++) {
		tag.removeAttribute(tag.attributes[i].nodeName);
	}
	console.log("new tag without attributes",tag);
}

/**
 * Method: editable_text_cleanup
 *		Очищает блок от "неверных" тегов
 *
 * Parameters:
 *		tag typeof jQuery		- Редактируемый блок который надо очистить
 */
LNEditor.prototype.editable_text_cleanup=function(tag)
{
	var t=this;

	var tagsmode=tag.attr("data-tags");
	// tagsmode == "" or "stdfmt"
//	var inside=tag.html();
	switch (tagsmode) {
		case "":
			// no tags allowed
			tag.find("> *").each(function(i,subtag) { $(subtag).replaceWith(subtag.innerText); });
			break;
		case "stdfmt":
			// могут быть только p, p > [i,u,b], blockquote, blockquote > [i,u,b]
			tag.find("> *").each(
				function(i,subtag) {
					// For base tags, leave only P or BLOCKQUOTE
					if (!subtag.tagName.match(/^(p|blockquote)$/i)) {
						var newtag=$("<p></p>").html(subtag.innerHtml);
						$(subtag).replaceWith(newtag);
						subtag=newtag[0];
					}
					// remove all attributes
					t._clean_attrs(subtag);
					// Inside must be I U B or nothing
					$(subtag).find("> *").each(function(i,subtag2) { if (subtag2.tagName.match(/^(i|b|strong|u)$/i)) return; $(subtag2).replaceWith(subtag2.innerText); });
//					$(subtag).replaceWith(subtag.innerText);
				}
			);
			break;
	}
}

/**
 * Method: edit_options_show
 *		Отображает менюшку с опциями для редактирования текста, типа I, U, B, CITE
 *
 * Parameters:
 *		tag typeof jQuery		- Редактируемый блок которого отобразить
 *		pos typeof Object		- Где показать
 */
LNEditor.prototype.edit_options_show=function(tag,pos)
{
	var t=this;
	this.edit_options_hide();
	if (!tag.attr("data-options")) return;
	var tmpl="<div class='LNEditor-edit-options'>";
	var arr=tag.attr("data-options").split(/,/);
	for (var i=0;i<arr.length;i++) {
		// это должен быть button а не div, потому что click на div меняет selection
		tmpl+="<button class='option option-"+arr[i]+"'>"+this.options[arr[i]].value+"</button>";
	}
	tmpl+="<div class='cl'></div><div class='tail'></div></div>";
	this._editoptions=tmpl=$(tmpl);
	$(".option",tmpl).bind("click",function(e) {t.edit_option_click(tag,e,this);});
	$("body").append(tmpl);
	if (pos) {
		tmpl.css("left",pos.x-Math.round(tmpl.width()/2));
		tmpl.css("top",pos.y-55+$("body").scrollTop());
	} else {
		tmpl.css("left",tag.offset().left);
		tmpl.css("top",tag.offset().top-45);
	}
}

/**
 * Method: edit_option_click
 *		Срабатывает при нажатии на кнопеу в менюшке с опциями для редактирования текста, типа I, U, B, CITE
 *
 * Parameters:
 *		tag typeof jQuery			- Редактируемый блок которого отобразить
 *		e typeof jQueryEvent		- Событие
 *		button typeof HTMLElement	- DIV с кнопкой
 */
LNEditor.prototype.edit_option_click=function(tag,e,button)
{
	e.preventDefault();
	e.stopPropagation();
	var buttonname=button.className.match(/option-(\w+)/)[1];
	var opt=this.options[buttonname];	
	if (opt) {
		if (opt.toggle) {
			var selection_info=this.get_selection_info();
			console.log("selection=",selection_info);
			if (selection_info && selection_info.tagName==opt.arg) {
				document.execCommand("formatBlock",false,"p");
			} else {
				document.execCommand(opt.command,false,opt.arg);
			}
		} else {
			document.execCommand(opt.command,false,opt.arg);
		}
	} else {
		console.log("edit_option_click("+buttonname+") - unknown");
	}
}

/**
 * Method: edit_options_hide
 *		Удаляет менюшку с опциями для редактирования текста
 *
 * Parameters:
 *		tag typeof jQuery		- Редактируемый блок которого отобразить
 *		e typeof jQueryEvent	- Событие
 */
LNEditor.prototype.edit_options_hide=function(tag,e)
{
	if (this._editoptions) {
		this._editoptions.remove();
		this._editoptions=undefined;
	}
}

/**
 * Method: editable_text_paste
 *		Срабатывает при вставке текста
 *
 * Parameters:
 *		tag typeof jQuery		- Редактируемый блок в который вставляется текст
 *		e typeof jQueryEvent	- Событие
 */
LNEditor.prototype.editable_text_paste=function(tag,e)
{

}

/**
 * Method: get_selection_info
 *		Возвращает информацию о теге внутри которого выбран текст
 */
LNEditor.prototype.get_selection_info=function()
{
	var stop_elements={
		"p":1,
		"h1":1,
		"h2":1,
		"h3":1,
		"h4":1,
		"div":1,
		"blockquote":1,
		"pre":1
	};
	var selection=document.getSelection();
	var el=selection.anchorNode;
	var tagName;
	if (el && el.tagName) tagName = el.tagName.toLowerCase();
	while (el && !stop_elements[tagName] && !el.contentEditable) {
		el=el.parentNode;
		if (el && el.tagName) tagName=el.tagName.toLowerCase();
	}
	return {
		el: el,
		tagName: tagName
	};
}
/**
 * Method: init_image_uploader
 *		Добавляет к картинке загрузчик
 */
LNEditor.prototype.init_image_uploader=function(tag)
{
	var t = this;
	if (!tag.fileupload) {
		console.log('no image upload plugin');
		return;
	}
	var uploader_block = $('<div class="loader_wrap"><div class="status"></div><input class="upload_button" type="file" name="img_file"></div>');	
	tag.after(uploader_block);
	
	t.upload_data.name = 'image';
	
	$('.status',uploader_block).html('Загрузить изображение');
	$('.upload_button',uploader_block).fileupload({
		url: t.upload_data.url,
		formData: t.upload_data,
		dataType: 'json',
		done: function (e, data) {
			t.image_upload_done(data.result,tag,uploader_block);
		},
		error: function (e, data) {
			console.log('image upload error ',e);
			$('.status',uploader_block).html('Ошибка');
			setTimeout(function(){$('.status',uploader_block).html('Загрузить изображение');},2500);
		},
		progressall: function (e, data) {
			var status = parseInt(data.loaded / data.total * 100, 10);//1..100%
			if (status>95) status = 95;
			$('.status',uploader_block).html(status+"%");
		},
	}).prop('disabled', !$.support.fileInput).parent().addClass($.support.fileInput ? undefined : 'disabled');
}
/**
 * Method: image_upload_done
 *		Срабатывает при попытке загрузить картинку
 */
LNEditor.prototype.image_upload_done=function(image,tag,uploader_block)
{
	var t = this;
	$('.status',uploader_block).html('Готово');
	setTimeout(function(){$('.status',uploader_block).html('Загрузить изображение');},2500);
	
	image.preview = tag.attr("data-preview") || '';
	//if (t.on_image_upload_func) t.on_image_upload_func(image,tag);
	t.load_image(image,tag);
}
/**
 * Method: image_upload_click
 *		Срабатывает при попытке загрузить картинку
 */
LNEditor.prototype.image_upload_click=function()
{

}

/**
 * Method: gen_save_object
 *		Возвращает JSON-объект с данными для сохранения
 */
LNEditor.prototype.gen_save_object=function()
{
	//TODO CHECK ABOUT IMAGE PREVIEW
	var t = this;
	var r=[];	
	$('.block').each(function(){
		var block = {};
		block.style_id = $(this).attr('data-id');
		block.content = {};
		block.im_ids = {};	
		$('.editable-text',this).each(function(){
			var field = $(this).attr('data-name');
			block.content[field] = $(this).html();
		});		
		$('.editable-image',this).each(function(){
			var field = $(this).attr('data-name');
			block.content[field] = $(this).attr('data-url');
			block.im_ids[field] = parseInt($(this).attr('data-im-id'));
		});		
		r.push(block);		
	});
	// r - массив с объектами типа тех что используются при add_block() - {style_id:x, content: {}}
	return r;
}

/**
 * Method: save
 */
LNEditor.prototype.save=function()
{
	var t = this;
	var obj=t.gen_save_object();
	this.body_json=obj;
	if (t.save_func) t.save_func(obj);
}
/*
 * 1) div -> p -> введите текст
 * 2) div -> p -> &nbsp;
 * 3) div -> p
 * 4) div
 * 
 * 5) div -> p -> some text
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */









